<?php
/**
* @author Duncan Dean Scholtz (duncandee@gmail.com) 
*/
class TableBase {
	
	
	function __construct($id = null, $load = false, $column = 'id') {
		$this->init();
		
		$loaderObject = (object) null;
		
		$loaderObject->loader_columnId = $id;
		$loaderObject->loader_columnName = $column;
		
		$className = get_class($this);
		$tableName = substr($className, 1);
		
		$loaderObject->loader_className  = $className;
		$loaderObject->loader_tableName  = $tableName;
		$loaderObject->loader_classTitle = str_replace('_', ' ', $tableName);
		
		
		$this->_tableName = $tableName;
		$this->_loaded = false;
		
		$loaderObject->loader_variables = $this->loader_variables;
		unset($this->loader_variables); // dont need to see these varibles it is has served its purpose
		
		$this->_loaderObject = base64_encode(serialize($loaderObject));
		if ($load) {
			$this->load();
		}
		return $loaderObject;
	}
	
	function loadArray($settings){
		if ($settings) {
			foreach ($settings as $key => $val) {
				$this->{$key} = $val;
			}
		}
	}
	
	private function load( $settings = null) {
		$loaderObject = $this->getLoaderObject();
		$db = F::get()->DB();
		
		if (is_null($settings)) {
			$sql = "
			SELECT `" . implode('`,`', array_keys($loaderObject->loader_variables)) . "`
			FROM `" . $loaderObject->loader_tableName . "`
			WHERE `" . $loaderObject->loader_columnName . "` = '" . $loaderObject->loader_columnId . "'";
			$settings = $db->getSingleArray($sql);
			if( F::get()->DB()->lastQueryHasError ){
				echo(F::get()->Tpl()->drawMessage('Loader', 'Unable to load Object here, please <a href="update">update</a>', 'error'));
			}
		}
		if ($settings) {
			$this->_loaded = true;
			$this->loadArray($settings);
		}
	}
	
	/*========== Overide functions ==========*/
	
	/**
	* Setup for the class to set variables
	*/
	public function init(){
		
	}
	/**
	* Function for display of table base
	*/
	public function draw(){
		$loaderObject = $this->getLoaderObject();
		if( $this->_loaded ){
			$this->drawEditLink();
			echo('<div class="row-fluid">');
			$this->view();
			echo('</div>');
		}else if( !empty($loaderObject->loader_columnId) && F::get()->Auth()->isAdmin() ){
			//TODO make this customisable for certain types of table bases
			echo(F::get()->Tpl()->drawMessage('Loader', 'Unable to load Object here, please <a>insert</a> module', 'error'));
		}
	}
	
	/**
	* Overide to draw draw on page ( custom )
	*/
	public function view(){
		$loaderObj = $this->getLoaderObject();
		
		if( $loaderObj->loader_variables ){
			foreach($loaderObj->loader_variables as $type=>$val){
				if( $val['datatype'] != 'Auto' ){
					echo($this->dataType($type, 'view'));
				}
			}
		}
	}
	/**
	* Overide for the edit view
	*/
	public function edit($postdata = array()){
		$loaderObj = $this->getLoaderObject();
		
		if( $loaderObj->loader_variables ){
			$dataFrom = F::get()->DataTypeForms();
			foreach($loaderObj->loader_variables as $type=>$val){
				if( $val['datatype'] != 'Auto' ){
					$dataFrom->add(ucfirst($type), $type);
				}
			}
			$dataFrom->draw('edit', 'edit', $this, $postdata['token']);
		}
	}
	
	public function postInit( $postdata = array()){
		$loaderVars = $this->getLoaderObject()->loader_variables;
		
		if( $loaderVars ){
			foreach($loaderVars as $key=>$val){
				$this->dataType($key, 'prepareInsert', $postdata );
			}
		}
		
		#Preparing data etc 
		$this->post($postdata);
	}
	/**
	* CRUD actions are handled here
	* @param $switch Switch action for developer to switch post callbacks
	* @param $postdata POST or get varbles ( mainly used in api )
	*/
	public function post( $postdata = array()){
		//Default TODO Update if it doesnt use ID column
		$db = F::get()->DB();
		if( $db->updateViaArray( $postdata['datatypeVal'], $this->_tableName, 'WHERE `id` = "'.$this->id.'"' ) ){
			F::get()->Tpl()->addMessage('Settings','Setting updated');
		}
	}
	
	/*========== Helper ==========*/
	
	
	public function getLoaderObject(){
		return unserialize(base64_decode($this->_loaderObject));
	}
	
	/**
	* Adds a variable to the loader to define the class 
	* @param $column Databse column referencing
	*	@param $datatype datatypes/ You would like to reference 
	* @param $defaultValue Default database value
	* @param $indexType P ( Primary Key ), I ( Index ) ,  U ( Unique ) , F ( Full Text )
	*	@param $length Overide for default length of datatypes
	*	@param $joinTable Creating relationships
	*	@param $joinColumn Column to link relationship to
	* @return mixed 
	*/
	
	protected function addLoaderVariable($column, $datatype, $defaultValue = '', $indexType = '', $length = null, $allowNULL = false,  $joinTable = null, $joinColumn = null){
		$this->loader_variables[$column]['datatype'] 		 = $datatype;
		$this->loader_variables[$column]['defaultValue'] = $defaultValue;
		$this->loader_variables[$column]['index'] 			 = strtolower($indexType);
		$this->loader_variables[$column]['length'] 			 = $length; //length overide
		$this->loader_variables[$column]['allowNULL'] 	 = $allowNULL;
		
		
		if( !is_null( $joinTable ) && !is_null( $joinColumn ) ){
			$this->loader_variables[$column]['join'] 				 = array('table' => $joinTable, 'column' =>$joinColumn);
		}
	}
	
	/**
	* Outputs the script for allowing editing of the TableBase element ( calls $this->edit() function )
	* @param 
	* @return mixed 
	*/
	private function drawEditLink(){
		if( F::get()->Auth()->isLoggedIn() ){
			echo('<a href="#" class="btn btn-small btn-success pull-right d-edit" rel="'.$this->getFormKey().'"><i class="icon-cog icon-white"></i> Edit</a><br/><br/>');
		}
	}
	
	
	private function drawInsertLink(){
		if( F::get()->Auth()->isLoggedIn() ){
			echo('<a href="#" class="btn btn-small btn-success pull-right d-insert" rel="'.$this->getFormKey().'"><i class="icon-cog icon-white"></i></a><br/><br/>');
		}
	}
	/**
	* Generated a key that contains all the infomation need for posting  a form
	* @param $switch String Switch for post function 
	* @return string 
	*/
	public function getFormKey(){
		$loaderObject = $this->getLoaderObject();
		
		$rel = array();
		$rel['columnId'] 	 = $loaderObject->loader_columnId;
		$rel['columnName'] = $loaderObject->loader_columnName;
		$rel['className']  = $loaderObject->loader_className;
		$rel['tableName']  = $loaderObject->loader_tableName;
		$rel['classTitle'] = $loaderObject->loader_classTitle;
		
		return F::get()->Crypt()->encrypt(json_encode($rel));
	}
	
	/**
	* 
	* @param $type string Refers to the column name eg. Users.`id` insert 'id' will access that column
	* @param $mode string Mode will target a specific function , edit , view etc
	* @param $extra array Contains infomation that is used for builing the inputs eg , array('uneditable'=>true) if you would like this field to be uneditable
	* @return mixed 
	*/
	public function dataType($type = '', $mode = 'view', &$extra = array()){
		$loaderObj = $this->getLoaderObject();
		$loaderVar = $loaderObj->loader_variables[$type];
		
		$datatype = F::get()->Datatype($loaderObj->loader_columnId, $loaderVar['datatype']);
		
		switch( $mode ){
			case 'edit':{
				return $datatype->edit($this->{$type}, 'datatypeVal['.$type.']', $extra);
				break;
			}
			case 'view':{
				return $datatype->view($this->{$type}, $extra);
				break;
			}
			case 'prepareInsert':{
				#handle file uploads for the file datatypes
				if( isset( $_FILES['datatypeVal_'.$type] ) ){
					$newValue = $datatype->prepareDatatypeFile('datatypeVal_'.$type);
				}else{
					#extra will be postdata
					$newValue = $datatype->prepareDatatypeVal($extra['datatypeVal'][$type]); 
				}
				#only set value if its changed 
				if( $newValue !== $extra['datatypeVal'][$type] ){
					$extra['datatypeVal'][$type]  = $newValue;
				}
				break;
			}
		}
	}
	
	
	
}

?>
